iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
1

提到資料之間的關係,我們就不得不提到 n+1 問題,以及怎麼解決。

什麼是 n+1 問題

以昨天的 UsersCities 舉例。

如果我們需要所有 Cities 相關 Usersname,我們可能會這樣寫:

City.all().joinToString{ city -> city.users.joinToString { it.name }}

如果我們這樣寫,那麼這段的 SQL 會是:

SELECT CITIES.ID FROM CITIES

SELECT USERS.ID, USERS."NAME", USERS.CITY FROM USERS WHERE USERS.CITY = 1
SELECT USERS.ID, USERS."NAME", USERS.CITY FROM USERS WHERE USERS.CITY = 2
SELECT USERS.ID, USERS."NAME", USERS.CITY FROM USERS WHERE USERS.CITY = 3

我們可以看到,第一個語法是撈出所有 city 資料的 SQL query。如果 CITY 有幾筆資料,我們就會產生幾筆 SQL query。

如果 city 的個數很少那還沒有關係,如果很多的話,那麼這段程式的效能就會很不好。

這個就是所謂的 n+1 問題。

eager loading

要解決這個問題,我們希望寫出來的程式可以不用這麼多的 SQL query 就找到我們需要的資料。

這裡,我們可以用 eager loading 的方式改寫:

City.all().with(City::users)

這樣改寫之後,這段 SQL 會變成是:

SELECT CITIES.ID FROM CITIES

SELECT USERS.ID, USERS."NAME", USERS.CITY FROM USERS WHERE USERS.CITY = 1
SELECT USERS.ID, USERS."NAME", USERS.CITY FROM USERS WHERE USERS.CITY IN (1, 2, 3)

無論 city 的個數是幾個,SQL query 的次數都會是 2 個。這樣我們就成功囉!


上一篇
[Day 18] 資料表關聯,DAO 的一對多關係
下一篇
[Day 20] exposed 的多對多關聯
系列文
最好用的非同步網頁框架!開始用 Ktor 寫 Kotlin Server30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言